﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web.Mvc;
using Utils.Share.Attributes;

namespace Utils.Share
{
    public static class Extension
    {
        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrWhiteSpace(value);
        }

        /// <summary>
        ///     安全返回值
        /// </summary>
        /// <param name="value">可空值</param>
        public static T SafeValue<T>(this T? value) where T : struct
        {
            return value ?? default(T);
        }

        /// <summary>
        ///     转换为字符串
        /// </summary>
        /// <param name="data">数据</param>
        public static string ToStr(this object data)
        {
            return data == null ? string.Empty : data.ToString().Trim();
        }

        /// <summary>
        ///     拼接集合元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="list">集合</param>
        /// <param name="quotes">引号，默认不带引号，范例：单引号 "'"</param>
        /// <param name="separator">分隔符，默认使用逗号分隔</param>
        public static string Splice<T>(this IEnumerable<T> list, string quotes = "", string separator = ",")
        {
            var result = new StringBuilder();
            foreach (var each in list)
                result.AppendFormat("{0}{1}{0}{2}", quotes, each, separator);
            return result.ToString().TrimEnd(separator.ToCharArray());
        }

        /// <summary>
        ///     获取值
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TProperty">属性类型</typeparam>
        /// <param name="helper">HtmlHelper</param>
        /// <param name="expression">属性表达式</param>
        public static object Value<TEntity, TProperty>(this HtmlHelper<TEntity> helper,
            Expression<Func<TEntity, TProperty>> expression)
        {
            var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
            return metadata.Model;
        }

        /// <summary>
        ///     获取验证特性的错误消息
        /// </summary>
        /// <param name="attribute">验证特性</param>
        public static string GetErrorMessage(this ValidationAttribute attribute)
        {
            if (attribute == null)
                return string.Empty;
            if (attribute.ErrorMessage.IsEmpty() == false)
                return attribute.ErrorMessage;
            return Resource.GetString(attribute.ErrorMessageResourceType.FullName, attribute.ErrorMessageResourceName,
                attribute.ErrorMessageResourceType.Assembly);
        }

        /// <summary>
        ///     获取最后一个属性
        /// </summary>
        /// <param name="propertyName">属性名，范例，A.B.C,返回"C"</param>
        public static string GetLastProperty(this string propertyName)
        {
            if (propertyName.IsEmpty())
                return string.Empty;
            var lastIndex = propertyName.LastIndexOf(".", StringComparison.Ordinal) + 1;
            return propertyName.Substring(lastIndex);
        }

        /// <summary>
        ///     转换为整型
        /// </summary>
        /// <param name="data">数据</param>
        public static int ToInt(this string data)
        {
            if (data == null)
                return 0;
            int result;

            int.TryParse(data, out result);

            return result;
        }

        #region GetDescription(获取描述)

        ///// <summary>
        ///// 获取描述
        ///// </summary>
        ///// <typeparam name="T">类型</typeparam>
        ///// <param name="memberName">成员名称</param>
        //public static string GetDescription<T>(string memberName)
        //{
        //    return GetDescription(Sys.GetType<T>(), memberName);
        //}

        /// <summary>
        ///     获取描述,使用System.ComponentModel.Description特性设置描述
        /// </summary>
        /// <param name="instance">枚举实例</param>
        public static string Description(this Enum instance)
        {
            var type = instance.GetType();

            return GetDescription(type, GetName(type, instance));
        }

        /// <summary>
        ///     获取描述
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="memberName">成员名称</param>
        public static string GetDescription(Type type, string memberName)
        {
            if (type == null)
                return string.Empty;
            return string.IsNullOrWhiteSpace(memberName)
                ? string.Empty
                : GetDescription(type, type.GetField(memberName));
        }

        /// <summary>
        ///     获取描述
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="field">成员</param>
        public static string GetDescription(Type type, FieldInfo field)
        {
            if (type == null)
                return string.Empty;
            if (field == null)
                return string.Empty;
            var attribute =
                field.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault() as DescriptionAttribute;
            return attribute == null ? field.Name : attribute.Description;
        }

        /// <summary>
        ///     获取成员名
        /// </summary>
        /// <param name="type">枚举类型</param>
        /// <param name="member">成员名、值、实例均可</param>
        public static string GetName(Type type, object member)
        {
            if (type == null)
                return string.Empty;
            if (member == null)
                return string.Empty;
            if (member is string)
                return member.ToString();
            return type.IsEnum == false ? string.Empty : Enum.GetName(type, member);
        }

        #endregion

        //#region ToLambda(创建Lambda表达式)

        ///// <summary>
        ///// 创建Lambda表达式
        ///// </summary>
        ///// <typeparam name="TDelegate">委托类型</typeparam>
        ///// <param name="body">表达式</param>
        ///// <param name="parameters">参数列表</param>
        //public static Expression<TDelegate> ToLambda<TDelegate>(this Expression body, params ParameterExpression[] parameters)
        //{
        //    return Expression.Lambda<TDelegate>(body, parameters);
        //}

        //#endregion

        #region GetItems(获取描述项集合)

        /// <summary>
        ///     获取描述项集合,文本设置为Description，值为Value
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        public static List<Item> GetItems<T>()
        {
            var enumType = Nullable.GetUnderlyingType(typeof (T)) ?? typeof (T);

            if (enumType.IsEnum == false)
                throw new InvalidOperationException(string.Format("类型 {0} 不是枚举", enumType));

            var result = new List<Item>();
            foreach (var field in enumType.GetFields())
                AddItem<T>(result, field, enumType);
            return result.OrderBy(t => t.SortId).ToList();
        }

        /// <summary>
        ///     添加描述项
        /// </summary>
        private static void AddItem<T>(ICollection<Item> result, FieldInfo field, Type enumType)
        {
            if (!field.FieldType.IsEnum)
                return;
            var value = GetValue<T>(field, enumType);
            var description = Reflection.GetDescription(enumType, field);
            var sortId = GetSortId(field);
            if (sortId == -1)
                sortId = value;
            result.Add(new Item(description, value.ToString(), sortId));
        }

        /// <summary>
        ///     获取值
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="field">枚举字段</param>
        /// <param name="enumType">枚举类型</param>
        private static int GetValue<T>(FieldInfo field, Type enumType)
        {
            var memberValue = enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null);
            return GetValue(Nullable.GetUnderlyingType(typeof (T)) ?? typeof (T), memberValue);
        }

        /// <summary>
        ///     获取成员值
        /// </summary>
        /// <typeparam name="T">枚举</typeparam>
        /// <param name="member">
        ///     成员名、值、实例均可，
        ///     范例:Enum1枚举有成员A=0,可传入"A"、0、Enum1.A，获取值0
        /// </param>
        public static int GetValue<T>(object member)
        {
            return GetValue(Nullable.GetUnderlyingType(typeof (T)) ?? typeof (T), member);
        }

        /// <summary>
        ///     获取成员值
        /// </summary>
        /// <param name="type">枚举类型</param>
        /// <param name="member">成员名、值、实例均可</param>
        public static int GetValue(Type type, object member)
        {
            var value = member.ToStr();
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentNullException("member");
            return (int) Enum.Parse(type, member.ToString(), true);
        }

        /// <summary>
        ///     获取排序号
        /// </summary>
        /// <param name="field">枚举字段</param>
        private static int GetSortId(FieldInfo field)
        {
            var attribute = field.GetCustomAttributes(typeof (OrderByAttribute), true).FirstOrDefault();
            if (attribute == null)
                return -1;
            return ((OrderByAttribute) attribute).SortId;
        }

        #endregion
    }
}